package stun

import (
	"callsips/internal/config"
	"github.com/pion/turn/v4"
	"github.com/zeromicro/go-zero/core/logx"
	"log"
	"net"
	"os"
	"os/signal"
	"strconv"
	"syscall"
	"time"
)

func StunInit(c config.Config) {
	// 生成用户认证密钥（基于 realm 和密码）
	usersMap := map[string][]byte{}
	usersMap[c.Turn.Username] = turn.GenerateAuthKey(c.Turn.Username, c.Turn.Realm, c.Turn.Password)

	udpListener, err := net.ListenPacket("udp4", "0.0.0.0:"+strconv.Itoa(c.Turn.ListenPort))
	if err != nil {
		log.Panicf("Failed to create TURN server listener: %s", err)
	}

	server, err := turn.NewServer(turn.ServerConfig{
		ChannelBindTimeout: time.Second * 2,
		Realm:              c.Turn.Realm,
		AuthHandler: func(username, realm string, srcAddr net.Addr) ([]byte, bool) {
			if key, ok := usersMap[username]; ok {
				return key, true
			}
			return nil, false
		},
		PacketConnConfigs: []turn.PacketConnConfig{
			{
				PacketConn: udpListener,
				RelayAddressGenerator: &turn.RelayAddressGeneratorStatic{
					RelayAddress: net.ParseIP(c.Turn.PublicIp), // 公网 IP
					Address:      "0.0.0.0",                    // 监听所有接口

				},
			},
		},
	})
	if err != nil {
		log.Panic(err)
	}

	logx.Infof("TURN 服务器运行中: public-ip=%s, port=%d, realm=%s", c.Turn.PublicIp, c.Turn.ListenPort, c.Turn.Realm)
	// Block until user sends SIGINT or SIGTERM
	sigs := make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
	<-sigs

	if err = server.Close(); err != nil {
		log.Panic(err)
	}
}
